package com.gmss.crawler.utils;

import cn.hutool.core.convert.Convert;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DateUtils {

    private DateUtils() {
    }

    // yyyy-MM-dd HH:mm:ss
    public static final String PATTERN_yyyy_MM_dd_HH_mm_ss = "^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\\s+(20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d$";
    // yyyy-MM-dd
    public static final String PATTERN_yyyy_MM_dd = "^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$";
    // yyyy/MM/dd HH:mm:ss
    public static final String PATTERN_yyyy_MM_dd_HH_mm_ss_TWO = "^[1-9]\\d{3}/(0[1-9]|1[0-2])/(0[1-9]|[1-2][0-9]|3[0-1])\\s+(20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d$";
    // yyyy/MM/dd
    public static final String PATTERN_yyyy_MM_dd_TWO = "^[1-9]\\d{3}/(0[1-9]|1[0-2])/(0[1-9]|[1-2][0-9]|3[0-1])$";
    // yyyyMMddHHmmss
    public static final String PATTERN_yyyy_MM_dd_HH_mm_ss_THREE = "^\\d{4}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])(0[1-9]|1\\d|2[0-3])(0[1-9]|[1-5]\\d){2}$";
    // yyyyMMdd
    public static final String PATTERN_yyyy_MM_dd_THREE = "^[1-9]\\d{3}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$";
    /**
     * 判断日期格式和范围
     */
    public static final String REXP = "^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))";


    final static Map<String, ThreadLocal<DateFormat>> THREAD_LOCAL_POOL = new HashMap<>();
    final static ThreadLocal<DateFormat> DEFAULT_THREAD_LOCAL = new ThreadLocal<DateFormat>() {
        @Override
        protected synchronized DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    static {
        THREAD_LOCAL_POOL.put("yyyy-MM-dd HH:mm:ss", DEFAULT_THREAD_LOCAL);
    }

    private static final ThreadLocal<DateFormat> formatThreadLocal_yMdHms = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };
    private static final ThreadLocal<DateFormat> FORMAT_THREAD_LOCAL_yyyy_MM_dd = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };
    private static final ThreadLocal<DateFormat> formatThreadLocal_yMdHms_two = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        }
    };
    private static final ThreadLocal<DateFormat> formatThreadLocal_yMd_two = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy/MM/dd");
        }
    };
    private static final ThreadLocal<DateFormat> formatThreadLocal_yMdHms_THREE = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMddHHmmss");
        }
    };
    private static final ThreadLocal<DateFormat> formatThreadLocal_yMd_THREE = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMdd");
        }
    };


    /**
     * date1往后推延dataExpire天数，与date2进行比较。
     *
     * @param date1        要修改的原始日期1
     * @param date2        要比较的日期2
     * @param compareField 比较类型 Calendar.MINUTE（毫秒），Calendar.DATE（天数），Calendar.YEAR（年）
     * @param dataExpire   要对日期1修改的变量步长
     * @return date1修改之后 小于、等于、大于date2，分别返回-1、0、1
     * System.out.println(compareAddDate(toDate("2018-11-03"), new Date(), Calendar.DATE, 1);
     */
    public static int compareAddDate(Date date1, Date date2, int compareField, int dataExpire) {
        // 先将date1对应的时间位置，增加对应的步长
        Date add1 = add(date1, compareField, dataExpire);
        // 返回对date1修改之后的两个日期的比较值
        return org.apache.commons.lang3.time.DateUtils.truncatedCompareTo(add1, date2, compareField);
    }

    /**
     * @deprecated
     */
    public static Date add(Date date, int calendarField, int dataExpire) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        } else {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(calendarField, dataExpire);
            return c.getTime();
        }
    }

    /**
     * 传入的 yyyy-MM-dd HH:mm:ss格式时间，返回距今月份
     *
     * @param inputDate
     * @return
     */
    public static int betweenNow(String inputDate) {
        DateTimeFormatter dateTimeFormatter;
        Pattern yMdHms = Pattern.compile(PATTERN_yyyy_MM_dd_HH_mm_ss);
        if (yMdHms.matcher(inputDate).matches()) {
            dateTimeFormatter = DateTimeFormatter.ofPattern(PATTERN_yyyy_MM_dd_HH_mm_ss);
        } else {
            dateTimeFormatter = DateTimeFormatter.ofPattern(PATTERN_yyyy_MM_dd);
        }
        LocalDate parse = LocalDate.parse(inputDate, dateTimeFormatter);
        LocalDate now = LocalDate.now();
        Period between = Period.between(parse, now);
        int months = (int) between.toTotalMonths();
        return months;
    }


    /**
     * 将yyyy-MM-dd HH:mm:ss 转成Date
     *
     * @param dateStr
     * @return
     * @throws ParseException
     */
    public static Date stringToDate(String dateStr) throws ParseException {
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }
        Pattern yMdHms = Pattern.compile(PATTERN_yyyy_MM_dd_HH_mm_ss);
        if (yMdHms.matcher(dateStr).matches()) {
            Date parse = formatThreadLocal_yMdHms.get().parse(dateStr);
            return parse;
        }
        Pattern yMd = Pattern.compile(PATTERN_yyyy_MM_dd);
        if (yMd.matcher(dateStr).matches()) {
            Date parse = FORMAT_THREAD_LOCAL_yyyy_MM_dd.get().parse(dateStr);
            return parse;
        }

        Pattern yMdHms2 = Pattern.compile(PATTERN_yyyy_MM_dd_HH_mm_ss_TWO);
        if (yMdHms2.matcher(dateStr).matches()) {
            Date parse = formatThreadLocal_yMdHms_two.get().parse(dateStr);
            return parse;
        }

        Pattern yMd2 = Pattern.compile(PATTERN_yyyy_MM_dd_TWO);
        if (yMd2.matcher(dateStr).matches()) {
            Date parse = formatThreadLocal_yMd_two.get().parse(dateStr);
            return parse;
        }

        Pattern yMdHms3 = Pattern.compile(PATTERN_yyyy_MM_dd_HH_mm_ss_THREE);
        if (yMdHms3.matcher(dateStr).matches()) {
            Date parse = formatThreadLocal_yMdHms_THREE.get().parse(dateStr);
            return parse;
        }

        Pattern yMd3 = Pattern.compile(PATTERN_yyyy_MM_dd_THREE);
        if (yMd3.matcher(dateStr).matches()) {
            Date parse = formatThreadLocal_yMd_THREE.get().parse(dateStr);
            return parse;
        }
        return null;
    }

    public static String toyMd(String dateStr) {
        return StringUtils.substring(dateStr, 0, 10);
    }

    /**
     * 另一种方式的格式转换
     *
     * @param dateStr yyyy-MM-dd
     * @return
     */
    public static Date toDateFromyMdStr(String dateStr) {
        try {
            return FORMAT_THREAD_LOCAL_yyyy_MM_dd.get().parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 当前日期往后增加天数.整数往后推,负数往前移动
     *
     * @param forwardNum 天数
     * @return
     */
    public static Date getForwardDate(int forwardNum) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(new Date());
        //把日期往后增加一天.整数往后推,负数往前移动
        calendar.add(calendar.DATE, forwardNum);
        //这个时间就是日期往后推一天的结果
        Date date = calendar.getTime();
        return date;
    }

    /**
     * @param list
     * @param initDate
     * @return
     */
    public static List<Date> getStartDateToYesterday(List<Date> list, Date initDate) {
        Date now = new Date();
        DateFormat df = new SimpleDateFormat(PATTERN_yyyy_MM_dd);
        try {
            if (initDate.getTime() > df.parse(df.format(now)).getTime()) {
                return list;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        list.add(initDate);
        Date newDate = getNextDate(initDate, 1);
        return getStartDateToYesterday(list, newDate);
    }

    /**
     * 获取开始时间到结束时间中的日期
     *
     * @param list
     * @param nextDate
     * @param endDate
     * @return
     */
    public static List<Date> getStartDateToEndDate(List<Date> list, Date nextDate, Date endDate) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        try {
            if (nextDate.getTime() > df.parse(df.format(endDate)).getTime()) {
                return list;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        list.add(nextDate);
        Date newDate = getNextDate(nextDate, 1);
        return getStartDateToEndDate(list, newDate, endDate);
    }

    /**
     * @param date      日期
     * @param dayNumber 把日期往后增加一天.（整数）往后推,（负数）往前移动
     * @return
     */
    public static Date getNextDate(Date date, int dayNumber) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        //把日期往后增加一天.整数往后推,负数往前移动
        calendar.add(calendar.DATE, dayNumber);
        //这个时间就是日期往后推一天的结果
        date = calendar.getTime();
        return date;
    }

    /**
     * 线程安全 date转String 默认格式yyyy-MM-dd HH:mm:ss
     *
     * @param date   日期
     * @param format 格式
     * @return
     */
    public static String dateToString(Date date, final String format) {
        if (format == null || "".equals(format.trim())) {
            return formatThreadLocal_yMdHms.get().format(date);
        }

        ThreadLocal<DateFormat> threadLocal = THREAD_LOCAL_POOL.get(format);
        if (threadLocal == null) {
            threadLocal = new ThreadLocal<DateFormat>() {
                @Override
                protected synchronized DateFormat initialValue() {
                    return new SimpleDateFormat(format);
                }
            };
            THREAD_LOCAL_POOL.put(format, threadLocal);
        }
        return threadLocal.get().format(date);
    }

    /**
     * date转String yyyy-MM-dd HH:mm:ss 线程安全
     *
     * @param date
     * @return
     */
    public static String getDate(Date date) {
        return DEFAULT_THREAD_LOCAL.get().format(date);
    }

    /**
     * 线程安全 String转Date
     *
     * @param dateStr 日期
     * @param format  格式
     * @return
     * @throws ParseException
     */
    public static Date stringToDateFormat(String dateStr, final String format) throws ParseException {
        ThreadLocal<DateFormat> threadLocal = THREAD_LOCAL_POOL.get(format);
        if (threadLocal == null) {
            threadLocal = new ThreadLocal<DateFormat>() {
                @Override
                protected synchronized DateFormat initialValue() {
                    return new SimpleDateFormat(format);
                }
            };
            THREAD_LOCAL_POOL.put(format, threadLocal);
        }
        return threadLocal.get().parse(dateStr);
    }


    /**
     * 验证日期是否正确
     *
     * @param date yyyy-MM-dd、yyyy/MM/dd、yyyyMMdd
     * @return true:正确，false:错误
     */
    public static boolean validateDate(String date) {
        Pattern pat = Pattern.compile(REXP);
        Matcher mat = pat.matcher(date);
        boolean dateType = mat.matches();
        return dateType;
    }

    /**
     * 实现取当前日期的上（下）个月的那一天。
     * 说明：像有些月的前一个月是没有31号的，则默认用这个月的30号;
     * 另外2月份也是一个特殊的月，闰年时为29天，非闰年为28天，所以闰年的3月份的30，31的上（下）个月为29号，
     * 非闰年的29，30，31号的上（下）一个月的同一天为28号。还有就是这个月是1月，这上（下）个月是去年的12月。
     * 通过传入一个yyyy-mm-dd的数据，如何实现上述需求，成功取得上（下）一个月的同一天！！
     *
     * @param dateStr yyyy-mm-dd日期
     * @param month   正数：当前日期往后推几月，负数：当前日期往前推几月
     * @return 返回null为格式错误
     */
    public static Date getDateOfLastMonth(String dateStr, int month) {
        // 验证日期是否正确,true:正确，false:错误
        if (!validateDate(dateStr))
            return null;

        try {
            Date parse = null;
            Pattern yMd = Pattern.compile(PATTERN_yyyy_MM_dd);
            if (yMd.matcher(dateStr).matches()) {
                parse = FORMAT_THREAD_LOCAL_yyyy_MM_dd.get().parse(dateStr);
            } else
                return parse;
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(parse);
            calendar.add(Calendar.MONTH, month);
            return calendar.getTime();
        } catch (ParseException e) {
            throw new IllegalArgumentException("Invalid date format: " + dateStr);
        }
    }


    /**
     * 计算时间差，以月份为单位
     *
     * @param startDate
     * @param endDate
     * @return 返回相差的月数
     */
    public static int getDistanceMonth(Date startDate, Date endDate) throws ParseException {
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(startDate);
        c2.setTime(endDate);
        int year = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);
        //开始日期若小月结束日期
        if (year < 0) {
            year = -year;
            return year * 12 + c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
        }
        return year * 12 + c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);
    }

    /**
     * 计算时间差，以天数为单位。如：2018-08-08 和 2018-08-05 相差3天
     *
     * @param startTime
     * @param endTime
     * @return 返回相差的天数
     */
    public static int getDistanceDay(Date startTime, Date endTime) {
        int days = 0;
        long time1 = startTime.getTime();
        long time2 = endTime.getTime();

        long diff;
        if (time1 < time2) {
            diff = time2 - time1;
        } else {
            diff = time1 - time2;
        }
        days = (int) (diff / (24 * 60 * 60 * 1000));
        return days;
    }

    /**
     * 计算时间差，以小时为单位。如：2018-08-08 和 2018-08-07 相差24h
     *
     * @param startTime
     * @param endTime
     * @return 返回相差的小时
     */
    public static int getDistanceHour(Date startTime, Date endTime) {
        int hour = 0;
        long time1 = startTime.getTime();
        long time2 = endTime.getTime();

        long diff;
        if (time1 < time2) {
            diff = time2 - time1;
        } else {
            diff = time1 - time2;
        }
        hour = (int) (diff / (60 * 60 * 1000));
        return hour;
    }

    /**
     * 计算时间差，以小时为单位，。
     * 如时间差小于一小时，按一时返回，
     * 如时间大于一小时，且小于二小时，按二时间返回，
     * 以此类推
     *
     * @param startTime
     * @param endTime
     * @return 返回相差的小时
     */
    public static int getDistanceHourRoundMin(Date startTime, Date endTime) {
        double hour = 0;
        long time1 = startTime.getTime();
        long time2 = endTime.getTime();

        long diff;
        if (time1 < time2) {
            diff = time2 - time1;
        } else {
            diff = time1 - time2;
        }
        BigDecimal diffBigDecimal = new BigDecimal(diff);
        int oneHour = 60 * 60 * 1000;
        BigDecimal hourBigDecimal = new BigDecimal(String.valueOf(oneHour));
        hour = diffBigDecimal.divide(hourBigDecimal, 4, BigDecimal.ROUND_HALF_UP).doubleValue();
        int aa = (int) Math.ceil(hour);
        return aa;
    }


    /**
     * 计算时间差-分钟
     *
     * @param startTime
     * @param endTime
     * @return 返回相差的分钟
     */
    public static int getDistanceMinute(Date startTime, Date endTime) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long time1 = startTime.getTime();
        long time2 = endTime.getTime();

        long diff;
        if (time1 < time2)
            diff = time2 - time1;
        else
            diff = time1 - time2;

        // 计算差多少分钟
        int min = (int) (diff % nd % nh / nm);
        return min;
    }

    /**
     * 计算时间差-秒
     *
     * @param startTime
     * @param endTime
     * @return 返回相差的秒数
     */
    public static int getDistanceSecond(Date startTime, Date endTime) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        long ns = 1000;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long time1 = startTime.getTime();
        long time2 = endTime.getTime();

        long diff;
        if (time1 < time2)
            diff = time2 - time1;
        else
            diff = time1 - time2;
        // 计算差多少秒//输出结果
        int sec = (int) (diff % nd % nh % nm / ns);
        return sec;
    }

    /**
     * 计算时间差，几天几时几分几秒
     *
     * @param startTime
     * @param endTime
     * @return 返回相差的日时分秒
     */
    public static String getTimeDiff(Date startTime, Date endTime) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        long ns = 1000;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long time1 = startTime.getTime();
        long time2 = endTime.getTime();

        long diff;
        if (time1 < time2)
            diff = time2 - time1;
        else
            diff = time1 - time2;

        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟" + sec + "秒";
    }


    /**
     * jdk8中的LocalDateTime转Date
     *
     * @param beforeDays 多少天之前
     * @return 日期
     */
    public static Date localDateTimeToDate(int beforeDays) {
        LocalDateTime now = LocalDateTime.now();
        now = now.minus(beforeDays, ChronoUnit.DAYS);
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = now.atZone(zone).toInstant();
        return Date.from(instant);
    }

    /**
     * jdk8中的LocalDateTime转Date
     *
     * @param localDateTime
     * @return
     */
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        return Date.from(instant);
    }

    /**
     * 时间戳转Date
     *
     * @param time
     * @return
     */
    public static Date getTimestampDate(Long time) {
        Calendar cal = Calendar.getInstance(Locale.ENGLISH);
        cal.setTimeInMillis(time);
        return cal.getTime();
    }

    /**
     * hutool日期转换，支持多种格式，yyyy/MM/dd,yyyy/M/d,yyyy.MM.dd,yyyy.M.d等,但不支持1920年01月
     *
     * @param dateDataStr
     * @return
     */
    public static Date hutoolConvert(String dateDataStr) {
        Date date = Convert.toDate(dateDataStr);
        return date;
    }

    /**
     * 时间戳，yyyy/MM/dd HH:mm:ss，yyyy/MM/dd，yyyy-MM-dd HH:mm:ss，yyyy-MM-dd HH:mm等格式转换成yyyy-MM-dd格式字符串返回
     *
     * @param text
     * @return
     * @throws Exception
     */
    public static String handleDate(String text) throws Exception {
        if (StringUtils.isEmpty(text)) {
            return null;
        }
        text = text.trim();
        String pattern_ymdhms = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}";
        String pattern_ymdhms2 = "\\d{4}/\\d{2}/\\d{2} \\d{2}:\\d{2}:\\d{2}";
        String pattern_ymdhm = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}";
        String pattern_ymd = "\\d{4}-\\d{2}-\\d{2}";
        String pattern_ymd_1 = "\\d{4}-\\d{2}-\\d{1}";
        String pattern_ymd_2 = "\\d{4}-\\d{1}-\\d{1}";
        String pattern_ymd_3 = "\\d{4}-\\d{1}-\\d{2}";
        String pattern_ymd_4 = "\\d{4}-\\d{2}";
        String pattern_ymd_5 = "\\d{4}-\\d{1}";
        String pattern_ymd2 = "\\d{4}/\\d{2}/\\d{2}";
        String pattern_ymd2_1 = "\\d{4}/\\d{2}/\\d{1}";
        String pattern_ymd2_2 = "\\d{4}/\\d{1}/\\d{1}";
        String pattern_ymd2_3 = "\\d{4}/\\d{1}/\\d{2}";
        String pattern_ymd2_4 = "\\d{4}/\\d{2}";
        String pattern_ymd2_5 = "\\d{4}/\\d{1}";
        String pattern_ymd3 = "\\d{4}年\\d{2}月\\d{2}日";
        String pattern_ymd3_1 = "\\d{4}年\\d{2}月\\d{2}";
        String pattern_ymd3_2 = "\\d{4}年\\d{2}月\\d{1}日";
        String pattern_ymd3_3 = "\\d{4}年\\d{1}月\\d{1}日";
        String pattern_ymd3_4 = "\\d{4}年\\d{1}月\\d{2}日";
        String pattern_ymd3_5 = "\\d{4}年\\d{1}月\\d{2}";
        String pattern_ymd3_6 = "\\d{4}年\\d{2}月\\d{1}";
        String pattern_ymd3_7 = "\\d{4}年\\d{1}月\\d{1}";
        String pattern_ymd4 = "\\d{4}年\\d{2}月";
        String pattern_ymd4_1 = "\\d{4}年\\d{2}";
        String pattern_ymd5 = "\\d{4}年\\d{1}月";
        String pattern_ymd5_1 = "\\d{4}年\\d{1}";
        String pattern_ymd6 = "\\d{4}年";
        String pattern_ymd7_1 = "\\d{4}\\.\\d{2}\\.\\d{2}";
        String pattern_ymd7_2 = "\\d{4}\\.\\d{2}\\.\\d{1}";
        String pattern_ymd7_3 = "\\d{4}\\.\\d{1}\\.\\d{1}";
        String pattern_ymd7_4 = "\\d{4}\\.\\d{1}\\.\\d{2}";
        String pattern_ymd7_5 = "\\d{4}\\.\\d{2}";
        String pattern_ymd7_6 = "\\d{4}\\.\\d{1}";
        String pattern_ymd7_7 = "\\d{4}";
        String pattern_ymd8 = "\\d{2}-\\d{2}-\\d{4}";
        String pattern_ymd8_1 = "\\d{2}/\\d{2}/\\d{4}";
        Date date = null;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat format_yyyyMM = new SimpleDateFormat("yyyy-MM");
        SimpleDateFormat format_yyyy = new SimpleDateFormat("yyyy");
        if (Pattern.matches(pattern_ymd3, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年MM月dd日");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd3_1, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年MM月dd");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd3_2, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年MM月d日");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd3_3, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年M月d日");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd3_4, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年M月dd日");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd3_5, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年M月dd日");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd3_6, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年MM月d");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd3_7, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年M月d");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd4, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年MM月");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd4_1, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年MM");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd5, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年MM月");
            date = format2.parse(text);
            return format_yyyyMM.format(date);
        } else if (Pattern.matches(pattern_ymd5_1, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年M");
            date = format2.parse(text);
            return format_yyyyMM.format(date);
        } else if (Pattern.matches(pattern_ymd6, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年");
            date = format2.parse(text);
            return format_yyyy.format(date);
        } else if (Pattern.matches(pattern_ymd7_1, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy.MM.dd");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd7_2, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy.MM.d");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd7_3, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy.M.d");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd7_4, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy.M.dd");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd7_5, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy.MM");
            date = format2.parse(text);
            return format_yyyyMM.format(date);
        } else if (Pattern.matches(pattern_ymd7_6, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy.M");
            date = format2.parse(text);
            return format_yyyyMM.format(date);
        } else if (Pattern.matches(pattern_ymd7_7, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy");
            date = format2.parse(text);
            return format_yyyy.format(date);
        } else if (Pattern.matches(pattern_ymdhms2, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd2, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy/MM/dd");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd2_1, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy/MM/d");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd2_2, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy/M/d");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd2_3, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy/M/dd");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd2_4, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy/MM");
            date = format2.parse(text);
            return format_yyyyMM.format(date);
        } else if (Pattern.matches(pattern_ymd2_5, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy/M");
            date = format2.parse(text);
            return format_yyyyMM.format(date);
        } else if (Pattern.matches(pattern_ymdhms, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymdhm, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd, text)) {
            return text;
        } else if (Pattern.matches(pattern_ymd_1, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-d");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd_2, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy-M-d");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd_3, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy-M-dd");
            date = format2.parse(text);
            return format.format(date);
        } else if (Pattern.matches(pattern_ymd_4, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM");
            date = format2.parse(text);
            return format_yyyyMM.format(date);
        } else if (Pattern.matches(pattern_ymd_5, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy-M");
            date = format2.parse(text);
            return format_yyyyMM.format(date);
        }  else if (Pattern.matches(pattern_ymd8, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("MM-dd-yyyy");
            date = format2.parse(text);
            return format.format(date);
        }   else if (Pattern.matches(pattern_ymd8_1, text)) {
            SimpleDateFormat format2 = new SimpleDateFormat("MM/dd/yyyy");
            date = format2.parse(text);
            return format.format(date);
        } else if (!StringUtils.isEmpty(text)) {
            Long time = Long.parseLong(text);
            String d = format.format(time);
            return d;
        }

        return null;
    }

    /**
     * 获取指定年月的第一天
     *
     * @param year
     * @param month
     * @return
     */
    public static String getFirstDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR, year);
        //设置月份
        cal.set(Calendar.MONTH, month - 1);
        //获取某月最小天数
        int firstDay = cal.getMinimum(Calendar.DATE);
        //设置日历中月份的最小天数
        cal.set(Calendar.DAY_OF_MONTH, firstDay);
        //格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }

    /**
     * 获取指定年月的最后一天
     *
     * @param year
     * @param month
     * @return
     */
    public static String getLastDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR, year);
        //设置月份
        cal.set(Calendar.MONTH, month - 1);
        //获取某月最大天数
        int lastDay = cal.getActualMaximum(Calendar.DATE);
        //设置日历中月份的最大天数
        cal.set(Calendar.DAY_OF_MONTH, lastDay);
        //格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }


    /**
     * 获取每天指定时间的date
     *
     * @param hour   时
     * @param min    分
     * @param second 秒
     */
    public static Date getEventDayAppointHour(int hour, int min, int second) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, hour);
        cal.set(Calendar.MINUTE, min);
        cal.set(Calendar.SECOND, second);
        return cal.getTime();
    }

    public static void main(String[] args) throws Exception {


        String startDateStr1 = "1920年01月09日";
        String startDateStr1_1 = "1920年1月9日";
        String startDateStr1_2 = "1920年11月9";
        String startDateStr1_3 = "1920年11月09";
        String startDateStr1_4 = "1920年11月09日";
        String startDateStr1_5 = "1920年1月9";
        String startDateStr1_6 = "1920年11月9日";
        String startDateStr2 = "1920年01月09";
        String startDateStr3 = "1920年01月";
        String startDateStr4 = "1920年01";
        String startDateStr5 = "1930.01.10";
        String startDateStr6 = "2021年6月8日";


        System.out.println(hutoolConvert(startDateStr1));
        System.out.println(hutoolConvert(startDateStr1_1));
        System.out.println(hutoolConvert(startDateStr1_2));
        System.out.println(hutoolConvert(startDateStr1_3));
        System.out.println(hutoolConvert(startDateStr1_4));
        System.out.println(hutoolConvert(startDateStr1_5));
        System.out.println(hutoolConvert(startDateStr1_6));
        System.out.println(hutoolConvert(startDateStr2));
        System.out.println(hutoolConvert(startDateStr3));
        System.out.println(hutoolConvert(startDateStr4));
        System.out.println(hutoolConvert(startDateStr5));
        System.out.println(hutoolConvert(startDateStr6));


//        System.out.println(handleDate(startDateStr1));
//        System.out.println(handleDate(startDateStr1_1));
//        System.out.println(handleDate(startDateStr1_2));
//        System.out.println(handleDate(startDateStr1_3));
//        System.out.println(handleDate(startDateStr1_4));
//        System.out.println(handleDate(startDateStr1_5));
//        System.out.println(handleDate(startDateStr1_6));
//        System.out.println(handleDate(startDateStr2));
//        System.out.println(handleDate(startDateStr3));
//        System.out.println(handleDate(startDateStr4));
//        System.out.println(handleDate(startDateStr5));
//        System.out.println(handleDate(startDateStr6));
//        String startDateStr = "1920-01-09";
//        System.out.println(getDistanceMonth(stringToDate(startDateStr), new Date()));
//        System.out.println(1221 / 12);
//        System.out.println(1221 % 12);
//
//        System.out.println(getTimestampDate(1629158400895L));
//        System.out.println(getFirstDayOfMonth(2021, 6));
//        System.out.println(getLastDayOfMonth(2021, 7));
//
//
//
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//        System.out.println(sdf.format(getDateOfLastMonth("2000-03-30", 1)));
//        System.out.println(sdf.format(getDateOfLastMonth("2000-03-31", 1)));


//        System.out.println(getNextDate(new Date(),1));
//        System.out.println(getDate(toDate("2018-02-30")));
//        System.out.println(toDate("2018-12-03 12:12:12"));
//        System.out.println(toDate("2018/12/03"));
//        System.out.println(toDate("2018/12/03 11:11:11"));
//        System.out.println(toDate("20181203"));
//        System.out.println(toDate("20181231230909"));
//        System.out.println(toDate("20181010"));
//        System.out.println(getDateStr(new Date(),"yyyy/MM/dd"));
//
//        Date date_ =toDate("2018-12-01");
//        System.out.println(compareAddDate(date_, new Date(), Calendar.DATE, 1));
//
//        System.out.println(localDateTimeToDate(1));
//
//        String date = getDate(new Date());
//        System.out.println(date);
//        String dateFormat = dateToStringFormat(new Date(),"yyyy-MM-dd");
//        System.out.println(dateFormat);
//        LocalDateTime now = LocalDateTime.now();
//        now = now.minus(Integer.parseInt("30"), ChronoUnit.DAYS);
//        Date dd = localDateTimeToDate(now);
//        System.out.println(dd);
//
//        String aa = "20181012103406";
//        Date yymmdd = stringToDateFormat(aa,"yyyyMMddHHmmss");
//
//        System.out.println(getDate(yymmdd));
//        System.out.println(validateDate("20181203"));
    }
}
